//! 数据验证工具模块
//! 
//! 对应Java中的AppValidationMgr类，提供各种数据格式验证功能

use regex::Regex;
use once_cell::sync::Lazy;
use uuid::Uuid;

/// 常用正则表达式
static EMAIL_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap()
});

static PHONE_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^1[3-9]\d{9}$").unwrap()
});

static ID_CARD_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[0-9Xx]$").unwrap()
});

static IP_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$").unwrap()
});

static URL_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^https?://[^\s/$.?#].[^\s]*$").unwrap()
});

static CHINESE_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[\u4e00-\u9fa5]+$").unwrap()
});

static NUMBER_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^\d+$").unwrap()
});

static LETTER_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[a-zA-Z]+$").unwrap()
});

static ALPHANUMERIC_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[a-zA-Z0-9]+$").unwrap()
});

static USERNAME_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[a-zA-Z][a-zA-Z0-9_.-]{3,31}$").unwrap()
});

static REAL_NAME_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[\u4E00-\u9FA5]{2,5}(?:·[\u4E00-\u9FA5]{1,5})*$").unwrap()
});

static VEHICLE_NO_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[\u4e00-\u9fa5]{1}[a-zA-Z]{1}[a-zA-Z_0-9]{5}$").unwrap()
});

static POSTAL_CODE_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^\d{6}$").unwrap()
});

static BANK_CARD_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^\d{12,19}$").unwrap()
});

/// 验证字符串是否为空或只包含空白字符
/// 
/// # Examples
/// ```
/// use librarys::validation::is_empty;
/// 
/// assert!(is_empty(""));
/// assert!(is_empty("   "));
/// assert!(is_empty("\t\n"));
/// assert!(!is_empty("hello"));
/// ```
pub fn is_empty(s: &str) -> bool {
    s.trim().is_empty()
}

/// 验证字符串是否不为空
/// 
/// # Examples
/// ```
/// use librarys::validation::is_not_empty;
/// 
/// assert!(!is_not_empty(""));
/// assert!(!is_not_empty("   "));
/// assert!(is_not_empty("hello"));
/// ```
pub fn is_not_empty(s: &str) -> bool {
    !is_empty(s)
}

/// 验证邮箱格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_email;
/// 
/// assert!(is_email("test@example.com"));
/// assert!(is_email("user.name+tag@domain.co.uk"));
/// assert!(!is_email("invalid.email"));
/// assert!(!is_email("@example.com"));
/// ```
pub fn is_email(email: &str) -> bool {
    EMAIL_REGEX.is_match(email)
}

/// 验证中国大陆手机号码格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_phone;
/// 
/// assert!(is_phone("13812345678"));
/// assert!(is_phone("15987654321"));
/// assert!(!is_phone("12345678901"));
/// assert!(!is_phone("1381234567"));
/// ```
pub fn is_phone(phone: &str) -> bool {
    PHONE_REGEX.is_match(phone)
}

/// 验证中国大陆身份证号码格式（18位）
/// 
/// # Examples
/// ```
/// use librarys::validation::is_id_card;
/// 
/// assert!(is_id_card("11010519491231002X"));
/// assert!(!is_id_card("123456789012345678"));
/// assert!(!is_id_card("11010519491301002X")); // 无效日期
/// ```
pub fn is_id_card(id_card: &str) -> bool {
    if !ID_CARD_REGEX.is_match(id_card) {
        return false;
    }
    
    // 验证身份证校验位
    validate_id_card_checksum(id_card)
}

/// 验证身份证校验位
fn validate_id_card_checksum(id_card: &str) -> bool {
    if id_card.len() != 18 {
        return false;
    }
    
    let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    let check_chars = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
    
    let mut sum = 0;
    let chars: Vec<char> = id_card.chars().collect();
    
    for i in 0..17 {
        if let Some(digit) = chars[i].to_digit(10) {
            sum += digit as usize * weights[i];
        } else {
            return false;
        }
    }
    
    let check_index = sum % 11;
    let expected_check_char = check_chars[check_index];
    let actual_check_char = chars[17].to_uppercase().next().unwrap_or(' ');
    
    actual_check_char == expected_check_char
}

/// 验证IP地址格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_ip_address;
/// 
/// assert!(is_ip_address("192.168.1.1"));
/// assert!(is_ip_address("127.0.0.1"));
/// assert!(!is_ip_address("256.1.1.1"));
/// assert!(!is_ip_address("192.168.1"));
/// ```
pub fn is_ip_address(ip: &str) -> bool {
    IP_REGEX.is_match(ip)
}

/// 验证URL格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_url;
/// 
/// assert!(is_url("https://www.example.com"));
/// assert!(is_url("http://example.com/path"));
/// assert!(!is_url("ftp://example.com"));
/// assert!(!is_url("not-a-url"));
/// ```
pub fn is_url(url: &str) -> bool {
    URL_REGEX.is_match(url)
}

/// 验证是否为纯数字
/// 
/// # Examples
/// ```
/// use librarys::validation::is_number;
/// 
/// assert!(is_number("12345"));
/// assert!(is_number("0"));
/// assert!(!is_number("12.34"));
/// assert!(!is_number("abc"));
/// ```
pub fn is_number(s: &str) -> bool {
    NUMBER_REGEX.is_match(s)
}

/// 验证是否为正整数
/// 
/// # Examples
/// ```
/// use librarys::validation::is_positive_integer;
/// 
/// assert!(is_positive_integer("123"));
/// assert!(!is_positive_integer("0"));
/// assert!(!is_positive_integer("-123"));
/// assert!(!is_positive_integer("12.34"));
/// ```
pub fn is_positive_integer(s: &str) -> bool {
    if let Ok(num) = s.parse::<i32>() {
        num > 0
    } else {
        false
    }
}

/// 验证是否为整数（包括正数、负数和零）
/// 
/// # Examples
/// ```
/// use librarys::validation::is_integer;
/// 
/// assert!(is_integer("123"));
/// assert!(is_integer("0"));
/// assert!(is_integer("-123"));
/// assert!(!is_integer("12.34"));
/// assert!(!is_integer("abc"));
/// ```
pub fn is_integer(s: &str) -> bool {
    s.parse::<i64>().is_ok()
}

/// 验证是否为浮点数
/// 
/// # Examples
/// ```
/// use librarys::validation::is_float;
/// 
/// assert!(is_float("12.34"));
/// assert!(is_float("-56.78"));
/// assert!(is_float("123.0"));
/// assert!(!is_float("abc"));
/// ```
pub fn is_float(s: &str) -> bool {
    s.parse::<f64>().is_ok()
}

/// 验证是否为纯字母
/// 
/// # Examples
/// ```
/// use librarys::validation::is_letter;
/// 
/// assert!(is_letter("abc"));
/// assert!(is_letter("ABC"));
/// assert!(is_letter("AbC"));
/// assert!(!is_letter("abc123"));
/// assert!(!is_letter("abc_def"));
/// ```
pub fn is_letter(s: &str) -> bool {
    LETTER_REGEX.is_match(s)
}

/// 验证是否为字母和数字组合
/// 
/// # Examples
/// ```
/// use librarys::validation::is_alphanumeric;
/// 
/// assert!(is_alphanumeric("abc123"));
/// assert!(is_alphanumeric("ABC"));
/// assert!(is_alphanumeric("123"));
/// assert!(!is_alphanumeric("abc_123"));
/// assert!(!is_alphanumeric("abc-123"));
/// ```
pub fn is_alphanumeric(s: &str) -> bool {
    ALPHANUMERIC_REGEX.is_match(s)
}

/// 验证是否为中文
/// 
/// # Examples
/// ```
/// use librarys::validation::is_chinese;
/// 
/// assert!(is_chinese("你好世界"));
/// assert!(is_chinese("中文"));
/// assert!(!is_chinese("hello"));
/// assert!(!is_chinese("你好world"));
/// ```
pub fn is_chinese(s: &str) -> bool {
    CHINESE_REGEX.is_match(s)
}

/// 验证用户名格式（字母开头，包含字母、数字、下划线、点、减号，长度4-32）
/// 
/// # Examples
/// ```
/// use librarys::validation::is_username;
/// 
/// assert!(is_username("user123"));
/// assert!(is_username("user.name"));
/// assert!(is_username("user_name"));
/// assert!(!is_username("123user")); // 数字开头
/// assert!(!is_username("usr")); // 太短
/// ```
pub fn is_username(username: &str) -> bool {
    USERNAME_REGEX.is_match(username)
}

/// 验证真实姓名格式（中文姓名）
/// 
/// # Examples
/// ```
/// use librarys::validation::is_real_name;
/// 
/// assert!(is_real_name("张三"));
/// assert!(is_real_name("欧阳修"));
/// assert!(is_real_name("爱新觉罗·启"));
/// assert!(!is_real_name("张"));
/// assert!(!is_real_name("Zhang San"));
/// ```
pub fn is_real_name(name: &str) -> bool {
    REAL_NAME_REGEX.is_match(name)
}

/// 验证车牌号格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_vehicle_number;
/// 
/// assert!(is_vehicle_number("京A12345"));
/// assert!(is_vehicle_number("沪B88888"));
/// assert!(!is_vehicle_number("A12345"));
/// assert!(!is_vehicle_number("京12345"));
/// ```
pub fn is_vehicle_number(vehicle_no: &str) -> bool {
    VEHICLE_NO_REGEX.is_match(vehicle_no)
}

/// 验证邮政编码格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_postal_code;
/// 
/// assert!(is_postal_code("100000"));
/// assert!(is_postal_code("200000"));
/// assert!(!is_postal_code("10000"));
/// assert!(!is_postal_code("1000000"));
/// ```
pub fn is_postal_code(postal_code: &str) -> bool {
    POSTAL_CODE_REGEX.is_match(postal_code)
}

/// 验证银行卡号格式
/// 
/// # Examples
/// ```
/// use librarys::validation::is_bank_card;
/// 
/// assert!(is_bank_card("6222021234567890123"));
/// assert!(is_bank_card("123456789012"));
/// assert!(!is_bank_card("12345"));
/// assert!(!is_bank_card("12345678901234567890"));
/// ```
pub fn is_bank_card(card_no: &str) -> bool {
    let clean_card = card_no.replace(' ', "");
    BANK_CARD_REGEX.is_match(&clean_card)
}

/// 验证是否包含特殊字符
/// 
/// # Examples
/// ```
/// use librarys::validation::has_special_character;
/// 
/// assert!(has_special_character("hello@world"));
/// assert!(has_special_character("test#123"));
/// assert!(!has_special_character("hello123"));
/// assert!(!has_special_character("HelloWorld"));
/// ```
pub fn has_special_character(s: &str) -> bool {
    let special_chars = r#"`~!@#$%^&*()+=|{}':;',\[\].<>?~！@#￥%……&*（）——+|{}【】'；：""'。，、？"#;
    s.chars().any(|c| special_chars.contains(c))
}

/// 验证字符串长度是否在指定范围内
/// 
/// # Examples
/// ```
/// use librarys::validation::is_length_in_range;
/// 
/// assert!(is_length_in_range("hello", 3, 10));
/// assert!(is_length_in_range("hello", 5, 5));
/// assert!(!is_length_in_range("hello", 6, 10));
/// assert!(!is_length_in_range("hello", 1, 4));
/// ```
pub fn is_length_in_range(s: &str, min: usize, max: usize) -> bool {
    let len = s.len();
    len >= min && len <= max
}

/// 验证是否为连续数字
/// 
/// # Examples
/// ```
/// use librarys::validation::is_continuous_numbers;
/// 
/// assert!(is_continuous_numbers("12345"));
/// assert!(is_continuous_numbers("890123"));
/// assert!(!is_continuous_numbers("13579"));
/// assert!(!is_continuous_numbers("hello"));
/// ```
pub fn is_continuous_numbers(s: &str) -> bool {
    if !is_number(s) || s.len() < 2 {
        return false;
    }
    
    let chars: Vec<char> = s.chars().collect();
    for i in 0..chars.len() - 1 {
        let current = chars[i].to_digit(10).unwrap_or(0);
        let next = chars[i + 1].to_digit(10).unwrap_or(0);
        let expected_next = if current == 9 { 0 } else { current + 1 };
        
        if next != expected_next {
            return false;
        }
    }
    
    true
}

/// 验证是否为连续字母
/// 
/// # Examples
/// ```
/// use librarys::validation::is_continuous_letters;
/// 
/// assert!(is_continuous_letters("abcd"));
/// assert!(is_continuous_letters("WXYZ"));
/// assert!(!is_continuous_letters("aceg"));
/// assert!(!is_continuous_letters("hello"));
/// ```
pub fn is_continuous_letters(s: &str) -> bool {
    if !is_letter(s) || s.len() < 2 {
        return false;
    }
    
    let s_lower = s.to_lowercase();
    let chars: Vec<char> = s_lower.chars().collect();
    
    for i in 0..chars.len() - 1 {
        let current = chars[i] as u8;
        let next = chars[i + 1] as u8;
        let expected_next = if current == b'z' { b'a' } else { current + 1 };
        
        if next != expected_next {
            return false;
        }
    }
    
    true
}

/// 验证日期格式是否正确（YYYYMMDD）
/// 
/// # Examples
/// ```
/// use librarys::validation::is_valid_date_string;
/// 
/// assert!(is_valid_date_string("20231225", 4));
/// assert!(is_valid_date_string("20240229", 4)); // 闰年
/// assert!(!is_valid_date_string("20230229", 4)); // 非闰年
/// assert!(!is_valid_date_string("20231301", 4)); // 无效月份
/// ```
pub fn is_valid_date_string(date_str: &str, year_len: usize) -> bool {
    let total_len = year_len + 4; // year + MM + DD
    if date_str.len() != total_len || !is_number(date_str) {
        return false;
    }
    
    let year: i32 = date_str[0..year_len].parse().unwrap_or(0);
    let month: u32 = date_str[year_len..year_len + 2].parse().unwrap_or(0);
    let day: u32 = date_str[year_len + 2..year_len + 4].parse().unwrap_or(0);
    
    if year <= 0 || month == 0 || month > 12 || day == 0 || day > 31 {
        return false;
    }
    
    // 检查特定月份的天数
    match month {
        4 | 6 | 9 | 11 => day <= 30,
        2 => {
            let is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
            day <= if is_leap { 29 } else { 28 }
        },
        _ => day <= 31,
    }
}

/// 生成UUID
/// 
/// # Examples
/// ```
/// use librarys::validation::generate_uuid;
/// 
/// let uuid_str = generate_uuid();
/// assert_eq!(uuid_str.len(), 32); // 去除连字符的UUID长度
/// assert!(!uuid_str.contains('-'));
/// ```
pub fn generate_uuid() -> String {
    Uuid::new_v4().to_string().replace('-', "").to_lowercase()
}

/// 手机号脱敏（中间4位显示为星号）
/// 
/// # Examples
/// ```
/// use librarys::validation::mask_phone;
/// 
/// assert_eq!(mask_phone("13812345678"), "138****5678");
/// assert_eq!(mask_phone("15987654321"), "159****4321");
/// ```
pub fn mask_phone(phone: &str) -> String {
    if phone.len() == 11 && is_phone(phone) {
        format!("{}****{}", &phone[0..3], &phone[7..11])
    } else {
        phone.to_string()
    }
}

/// 身份证号脱敏（中间10位显示为星号）
/// 
/// # Examples
/// ```
/// use librarys::validation::mask_id_card;
/// 
/// assert_eq!(mask_id_card("11010519491231002X"), "1101**********002X");
/// ```
pub fn mask_id_card(id_card: &str) -> String {
    if id_card.len() == 18 {
        format!("{}**********{}", &id_card[0..4], &id_card[14..18])
    } else {
        id_card.to_string()
    }
}

/// 银行卡号脱敏（只显示最后4位）
/// 
/// # Examples
/// ```
/// use librarys::validation::mask_bank_card;
/// 
/// assert_eq!(mask_bank_card("6222021234567890123"), "**** **** **** *0123");
/// ```
pub fn mask_bank_card(card_no: &str) -> String {
    if card_no.len() >= 4 {
        let last_four = &card_no[card_no.len() - 4..];
        format!("**** **** **** *{}", last_four)
    } else {
        card_no.to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_validation() {
        assert!(is_empty(""));
        assert!(is_empty("   "));
        assert!(!is_empty("hello"));
        
        assert!(is_not_empty("hello"));
        assert!(!is_not_empty(""));
    }

    #[test]
    fn test_email_validation() {
        assert!(is_email("test@example.com"));
        assert!(is_email("user.name+tag@domain.co.uk"));
        assert!(!is_email("invalid.email"));
        assert!(!is_email("@example.com"));
        assert!(!is_email("test@"));
    }

    #[test]
    fn test_phone_validation() {
        assert!(is_phone("13812345678"));
        assert!(is_phone("15987654321"));
        assert!(is_phone("18612345678"));
        assert!(!is_phone("12345678901"));
        assert!(!is_phone("1381234567"));
        assert!(!is_phone("1081234567"));
    }

    #[test]
    fn test_number_validation() {
        assert!(is_number("12345"));
        assert!(is_number("0"));
        assert!(!is_number("12.34"));
        assert!(!is_number("abc"));
        
        assert!(is_positive_integer("123"));
        assert!(!is_positive_integer("0"));
        assert!(!is_positive_integer("-123"));
        
        assert!(is_integer("123"));
        assert!(is_integer("0"));
        assert!(is_integer("-123"));
        assert!(!is_integer("12.34"));
        
        assert!(is_float("12.34"));
        assert!(is_float("-56.78"));
        assert!(is_float("123.0"));
    }

    #[test]
    fn test_string_type_validation() {
        assert!(is_letter("abc"));
        assert!(is_letter("ABC"));
        assert!(!is_letter("abc123"));
        
        assert!(is_alphanumeric("abc123"));
        assert!(is_alphanumeric("ABC"));
        assert!(!is_alphanumeric("abc_123"));
        
        assert!(is_chinese("你好世界"));
        assert!(!is_chinese("hello"));
        assert!(!is_chinese("你好world"));
    }

    #[test]
    fn test_format_validation() {
        assert!(is_username("user123"));
        assert!(is_username("user.name"));
        assert!(!is_username("123user"));
        assert!(!is_username("usr"));
        
        assert!(is_real_name("张三"));
        assert!(is_real_name("欧阳修"));
        assert!(!is_real_name("张"));
        
        assert!(is_vehicle_number("京A12345"));
        assert!(!is_vehicle_number("A12345"));
        
        assert!(is_postal_code("100000"));
        assert!(!is_postal_code("10000"));
        
        assert!(is_bank_card("6222021234567890123"));
        assert!(!is_bank_card("12345"));
    }

    #[test]
    fn test_continuous_validation() {
        assert!(is_continuous_numbers("12345"));
        assert!(is_continuous_numbers("890123"));
        assert!(!is_continuous_numbers("13579"));
        
        assert!(is_continuous_letters("abcd"));
        assert!(is_continuous_letters("WXYZ"));
        assert!(!is_continuous_letters("aceg"));
    }

    #[test]
    fn test_masking() {
        assert_eq!(mask_phone("13812345678"), "138****5678");
        assert_eq!(mask_id_card("11010519491231002X"), "1101**********002X");
        assert_eq!(mask_bank_card("6222021234567890123"), "**** **** **** *0123");
    }

    #[test]
    fn test_date_validation() {
        assert!(is_valid_date_string("20231225", 4));
        assert!(is_valid_date_string("20240229", 4)); // 闰年
        assert!(!is_valid_date_string("20230229", 4)); // 非闰年
        assert!(!is_valid_date_string("20231301", 4)); // 无效月份
    }

    #[test]
    fn test_utility_functions() {
        assert!(has_special_character("hello@world"));
        assert!(!has_special_character("hello123"));
        
        assert!(is_length_in_range("hello", 3, 10));
        assert!(!is_length_in_range("hello", 6, 10));
        
        let uuid = generate_uuid();
        assert_eq!(uuid.len(), 32);
        assert!(!uuid.contains('-'));
    }
}